<!-- common/image-upload/image-upload.vue -->
<template>
  <view class="ui-media-upload" :class="['is-' + dir]">
    <!-- 上传控制按钮 - 仅在非只读模式下显示 -->
    <view class="ui-media-upload__control" v-if="canShowControl && !readonly" @click="handleControlClick">
      <slot name="handle" :loading="uploading">
        <view class="ui-media-upload__control-main">
          <view class="ui-media-upload__control-text">{{ '+' + controlTitle }}</view>
        </view>
      </slot>
    </view>
    <template v-if="mediaList && mediaList.length && mediaList.length>0 && showFileList">
      <view
          class="ui-media-upload__item"
          v-for="(item, index) in mediaList"
          :key="index"
      >
        <slot name="media" :data="item">
          <!-- 视频预览 -->
          <view v-if="isVideo(item.path)" class="ui-media-upload__video-preview" @click="playVideo(item.path)">
            <video
                :src="ensureFullUrl(item.previewPath || item.path)"
                :controls="false"
                :show-center-play-btn="false"
                :show-play-btn="false"
                :show-fullscreen-btn="false"
                :show-mute-btn="false"
                :enable-progress-gesture="false"
                :object-fit="'cover'"
                width="80rpx"
                height="80rpx"
                :autoplay="false"
                :loop="false"
                @error="onVideoError"
            ></video>
            <view class="ui-media-upload__video-overlay">
              <view class="ui-media-upload__play-icon"></view>
            </view>
          </view>
          <!-- 图片预览 -->
          <ui-image
              v-else
              :src="ensureFullUrl(item.previewPath || item.path)"
              :preview-src="ensureFullUrl(item.path)"
              width="80rpx"
              height="80rpx"
              :border="true"
              @click="previewImage(item.path)"
          ></ui-image>
        </slot>

        <!-- 新增：上传进度和速率显示 -->
        <view v-if="loadingMap[item.path]" class="ui-media-upload__upload-info">
          <view class="ui-media-upload__progress-bar">
            <view class="ui-media-upload__progress-fill" :style="{ width: uploadProgressMap[item.path] + '%' }"></view>
          </view>
          <view class="ui-media-upload__progress-text">{{ uploadProgressMap[item.path] }}%</view>
          <view class="ui-media-upload__speed-text" v-if="uploadSpeedMap[item.path]">速率: {{ uploadSpeedMap[item.path] }} KB/s</view>
        </view>

        <view class="ui-media-upload__loading" v-if="loadingMap[item.path]">
          <ui-icon name="loading" size="24px" color="#007aff"></ui-icon>
        </view>
        <!-- 删除按钮 - 仅在非只读模式下显示 -->
        <view v-if="editable && !readonly" class="ui-media-upload__item-remove" @click="handleRemoveMediaClick(item, index)">
          <view class="ui-media-upload__item-remove-btn"></view>
        </view>
      </view>
    </template>

    <!-- 视频播放弹窗 -->
    <view class="ui-media-upload__video-modal" v-if="showVideoModal" @click="closeVideoModal">
      <view class="ui-media-upload__video-container" @click.stop>
        <video
            :src="ensureFullUrl(currentVideoSrc)"
            :controls="true"
            :autoplay="true"
            :show-fullscreen-btn="true"
            :show-mute-btn="true"
            :enable-progress-gesture="true"
            object-fit="contain"
            style="width: 100%; height: 400rpx;"
            :show-center-play-btn="true"
            :show-play-btn="true"
            @error="onModalVideoError"
        ></video>
        <view class="ui-media-upload__video-close" @click="closeVideoModal">×</view>
      </view>
    </view>
  </view>
</template>

<script>
import { uploadFileToTencentClound } from '@/apis/upload'
import { pathToBase64 } from 'image-tools'
import storage from "@huntianning/miniprogram/utils/storage";

export default {
  name: "bi-media-upload-order",
  props: {
    value: {
      type: [String, Array]
    },
    multiple: {
      type: Boolean,
      default: false
    },
    title: {
      type: String,
      default: '' // 默认为空，使用动态标题
    },
    editable: {
      type: Boolean,
      default: true
    },
    dir: {
      type: String,
      default: 'horizon',
      validator (value) {
        return ['horizon', 'vertical'].includes(value)
      }
    },
    showFileList: {
      type: Boolean,
      default: true
    },
    upload: {
      type: Boolean,
      default: false
    },
    maxCount: {
      type: Number,
      default: 9
    },
    sourceType: {
      type: Array,
      default: () => ['album', 'camera']
    },
    // 修改 mediaType 默认值，支持只选择图片、只选择视频或都选择
    mediaType: {
      type: String,
      default: 'all', // 'image', 'video', 'all'
      validator(value) {
        return ['image', 'video', 'all'].includes(value)
      }
    },
    // 新增 readonly 属性，用于查看模式
    readonly: {
      type: Boolean,
      default: false
    },
    // 新增压缩相关属性
    compress: {
      type: Boolean,
      default: true
    },
    // 图片压缩质量（0-1之间）
    imageQuality: {
      type: Number,
      default: 0.9,
      validator(value) {
        return value >= 0 && value <= 1
      }
    },
    // 视频压缩质量（0-1之间）
    videoQuality: {
      type: Number,
      default: 0.7,
      validator(value) {
        return value >= 0 && value <= 1
      }
    },
    // 最大宽度
    maxWidth: {
      type: Number,
      default: 1920
    },
    // 最大高度
    maxHeight: {
      type: Number,
      default: 1080
    },
    // 视频最大时长（秒）
    maxDuration: {
      type: Number,
      default: 60
    }
  },
  data () {
    return {
      mediaList: [],
      loadingMap: {},
      showVideoModal: false,
      currentVideoSrc: '',
      disableSyncMediaList: false,
      // 新增：用于跟踪每个文件的上传进度和速率
      uploadProgressMap: {}, // 存储每个文件的上传进度（0-100）
      uploadSpeedMap: {},    // 存储每个文件的上传速率（例如，KB/s）
      uploadStartTimeMap: {} // 存储每个文件的上传开始时间
    }
  },
  computed: {
    canShowControl() {
      // 在只读模式下不显示控制按钮
      if (this.readonly) {
        return false
      }
      // 始终显示控制按钮，除非达到最大数量或不可编辑
      if (!this.editable) {
        return false
      }
      if (this.mediaList && this.mediaList.length >= this.maxCount) {
        return false
      }
      return true
    },
    uploading () {
      return Object.keys(this.loadingMap).length > 0
    },
    // 动态控制标题显示
    controlTitle() {
      // 如果用户自定义了title，则优先使用自定义title
      if (this.title) {
        return this.title;
      }

      // 根据mediaType显示不同的默认标题
      switch (this.mediaType) {
        case 'image':
          return  this.$t('select-Images')
        case 'video':
          return this.$t('select-Video')
        case 'all':
        default:
          return this.$t('select-Media')
      }
    }
  },
  watch: {
    value: {
      handler(newVal) {
        if (!this.disableSyncMediaList) {
          this.syncMediaList()
        }
      },
      immediate: true
    }
  },
  created () {
    this.syncMediaList()
    // 设置语言
    let savedLanguage = uni.getStorageSync('language') || 'zh';
    const currentTimeType = storage.get('CURRENT_TIME_TYPE');
    savedLanguage = (currentTimeType === 1 || currentTimeType === '1') ? 'en' : 'zh';
    if (savedLanguage) {
      this.$i18n.locale = savedLanguage;
    }
  },
  methods: {
    handleControlClick () {
      let mediaCount = this.maxCount - (this.mediaList ? this.mediaList.length : 0)
      if (mediaCount <= 0) {
        return
      }

      // 根据平台选择不同的API
      // #ifdef H5
      this.chooseMediaH5(mediaCount)
      // #endif

      // #ifndef H5
      this.chooseMediaNative(mediaCount)
      // #endif
    },

    // H5平台选择媒体
    chooseMediaH5(count) {
      // 根据 mediaType 设置支持的文件扩展名
      let extension = []
      if (this.mediaType === 'image') {
        extension = ['jpeg', 'jpg', 'png', 'gif', 'webp']
      } else if (this.mediaType === 'video') {
        extension = ['mp4', 'mov', 'avi', 'wmv']
      } else {
        extension = ['jpeg', 'jpg', 'png', 'gif', 'webp', 'mp4', 'mov', 'avi', 'wmv']
      }

      uni.chooseImage({
        sizeType: 'compressed',
        count: count,
        sourceType: this.sourceType,
        extension: extension,
        success: ({ tempFiles, tempFilePaths }) => {
          const files = tempFilePaths.map((v, i) => {
            return {
              path: v,
              file: tempFiles[i],
              type: this.getFileType(v)
            }
          })
          files.forEach(file => {
            this.addFile(file)
          })
        },
        fail: (err) => {
          console.error('选择媒体失败', err)
        }
      })
    },

    // 原生平台选择媒体（添加视频压缩）
    chooseMediaNative(count) {
      // #ifdef APP-PLUS
      plus.gallery.pick(
          async (e) => {
            // 根据 mediaType 过滤选择的文件
            let filteredFiles = e.files
            if (this.mediaType === 'image') {
              filteredFiles = e.files.filter(file => this.isImage(file.path))
            } else if (this.mediaType === 'video') {
              filteredFiles = e.files.filter(file => this.isVideo(file.path))
            }

            const files = []
            for (let i = 0; i < filteredFiles.length; i++) {
              const file = filteredFiles[i]
              let filePath = file.path

              // 如果启用了压缩，对图片或视频进行压缩
              if (this.compress) {
                try {
                  if (this.isImage(filePath)) {
                    filePath = await this.compressImage(filePath)
                  } else if (this.isVideo(filePath)) {
                    filePath = await this.compressVideo(filePath)
                  }
                } catch (err) {
                  console.error('媒体压缩失败:', err)
                }
              }

              files.push({
                path: filePath,
                type: this.getFileType(filePath)
              })
            }

            files.forEach(file => {
              this.addFile(file)
            })
          },
          (err) => {
            console.error('选择媒体失败', err)
          },
          {
            filter: 'none',
            multiple: this.multiple,
            maximum: count,
            filename: '_doc/gallery/',
            permissionAlert: true
          }
      )
      // #endif

      // #ifdef MP-WEIXIN
      // 根据 mediaType 设置媒体类型
      let mediaTypes = []
      if (this.mediaType === 'image') {
        mediaTypes = ['image']
      } else if (this.mediaType === 'video') {
        mediaTypes = ['video']
      } else {
        mediaTypes = ['image', 'video']
      }

      uni.chooseMedia({
        count: count,
        mediaType: mediaTypes,
        sourceType: this.sourceType,
        maxDuration: this.maxDuration,
        camera: 'back',
        success: async ({ tempFiles, type }) => {
          const files = []
          for (let i = 0; i < tempFiles.length; i++) {
            const v = tempFiles[i]
            let filePath = v.tempFilePath

            // 如果启用了压缩，对图片或视频进行压缩
            if (this.compress) {
              try {
                if (type === 'image') {
                  filePath = await this.compressImage(filePath)
                } else if (type === 'video') {
                  filePath = await this.compressVideo(filePath)
                }
              } catch (err) {
                console.error('媒体压缩失败:', err)
              }
            }

            files.push({
              path: filePath,
              file: v,
              type: type,
              duration: v.duration,
              size: v.size
            })
          }

          files.forEach(file => {
            this.addFile(file)
          })
        },
        fail: (err) => {
          console.error('选择媒体失败', err)
        }
      })
      // #endif
    },

    handleRemoveMediaClick (item, index) {
      // 在只读模式下不允许删除
      if (this.readonly) {
        return
      }
      let title = this.$t('confirm_delete_media');
      uni.showModal({
        "cancelText": this.$t('delete'),
        'confirmText': this.$t('confirm'),
        'confirmColor':"#F18662",
        'content':title,
        'success': (ress) => {
          if (ress.confirm) {
            this.mediaList.splice(index, 1)
            this.refreshValue()
            // 强制更新视图
            this.$forceUpdate()
          } else {
            return
          }
        }
      })
    },

    syncMediaList () {
      if (this.value === undefined || this.value === null) {
        this.mediaList = []
        return
      }

      let mediaList = []
      if (this.multiple) {
        if (Array.isArray(this.value)) {
          mediaList = this.value.map(v => {
            if (typeof v === 'string') {
              return {
                status: 'done',
                path: v,
                type: this.getFileType(v)
              }
            } else {
              return v
            }
          })
        } else if (this.value) {
          mediaList = [{
            status: 'done',
            path: this.value,
            type: this.getFileType(this.value)
          }]
        }
      } else {
        if (this.value) {
          mediaList = [{
            status: 'done',
            path: this.value,
            type: this.getFileType(this.value)
          }]
        }
      }
      this.mediaList = mediaList
    },

    addFile (file) {
      // 在只读模式下不允许添加文件
      if (this.readonly) {
        return
      }

      // #ifdef APP-PLUS
      if (this.isImage(file.path)) {
        pathToBase64(file.path).then(base64 => {
          file.previewPath = base64
          this._addFile(file)
        }).catch(() => {
          this._addFile(file)
        })
      } else {
        this._addFile(file)
      }
      // #endif

      // #ifndef APP-PLUS
      this._addFile(file)
      // #endif
    },

    _addFile (file) {
      // 在只读模式下不允许添加文件
      if (this.readonly) {
        return
      }

      // 检查是否超过最大数量
      if (this.mediaList.length >= this.maxCount) {
        uni.showToast({
          title: `最多只能上传${this.maxCount}个文件`,
          icon: 'none'
        })
        return
      }

      // 检查文件类型是否符合要求
      if (this.mediaType === 'image' && !this.isImage(file.path)) {
        uni.showToast({
          title: '只能上传图片文件',
          icon: 'none'
        })
        return
      }

      if (this.mediaType === 'video' && !this.isVideo(file.path)) {
        uni.showToast({
          title: '只能上传视频文件',
          icon: 'none'
        })
        return
      }

      if (this.upload) {
        // 对于单选模式，清空现有列表
        if (!this.multiple) {
          this.mediaList = []
          this.loadingMap = {}
          this.uploadProgressMap = {}
          this.uploadSpeedMap = {}
          this.uploadStartTimeMap = {}
        }

        this.mediaList.push(file)
        this.$set(this.loadingMap, file.path, true)
        // 初始化进度和速率
        this.$set(this.uploadProgressMap, file.path, 0)
        this.$set(this.uploadSpeedMap, file.path, 0)
        this.$set(this.uploadStartTimeMap, file.path, Date.now())

        // 强制更新视图
        this.$forceUpdate()

        // 调用上传函数，假设 uploadFileToTencentClound 支持 progress 回调
        this.performUpload(file)
      } else {
        // 对于单选模式，清空现有列表
        if (!this.multiple) {
          this.mediaList = []
        }

        this.mediaList.push(file)
        this.refreshValue()
        // 强制更新视图
        this.$forceUpdate()
      }
    },

    refreshValue () {
      // 在只读模式下不需要更新值
      if (this.readonly) {
        return
      }

      if (this.upload) {
        let nextValue = this.mediaList.filter(v => v.status === 'done').map(v => v.path)
        this.disableSyncMediaList = true
        if (!this.multiple) {
          nextValue = nextValue.length > 0 ? nextValue[0] : null
        }
        this.$emit('input', nextValue)
        this.$nextTick(() => {
          this.disableSyncMediaList = false
        })
      } else {
        let nextValue = [...this.mediaList]
        if (!this.multiple) {
          nextValue = nextValue.length > 0 ? nextValue[0] : null
        }
        this.$emit('input', nextValue)
      }
      // 强制更新视图
      this.$forceUpdate()
    },

    // 图片压缩方法
    compressImage(filePath) {
      return new Promise((resolve, reject) => {
        // #ifdef MP-WEIXIN
        // 微信小程序使用自带的压缩功能
        if (this.compress) {
          uni.compressImage({
            src: filePath,
            quality: this.imageQuality * 100, // 微信接受0-100的值
            width: this.maxWidth.toString(),
            height: this.maxHeight.toString(),
            success: (res) => {
              resolve(res.tempFilePath)
            },
            fail: (err) => {
              console.error('微信图片压缩失败:', err)
              resolve(filePath) // 压缩失败时使用原图
            }
          })
        } else {
          resolve(filePath)
        }
        // #endif

        // #ifdef APP-PLUS
        // APP平台使用plus压缩
        if (this.compress) {
          plus.zip.compressImage(
              { src: filePath, dst: "_doc/compressed.jpg", quality: this.imageQuality * 100, width: this.maxWidth, height: this.maxHeight },
              (zip) => {
                resolve(zip.target)
              },
              (error) => {
                console.error('APP图片压缩失败:', error)
                resolve(filePath) // 压缩失败时使用原图
              }
          )
        } else {
          resolve(filePath)
        }
        // #endif

        // #ifdef H5
        // H5平台直接使用原图
        resolve(filePath)
        // #endif
      })
    },

    // 视频压缩方法
    compressVideo(filePath) {
      return new Promise((resolve, reject) => {
        // #ifdef MP-WEIXIN
        // 微信小程序：返回原路径，提示用户
        console.warn('微信小程序暂不支持前端视频压缩，请在服务端处理');
        resolve(filePath)
        // #endif

        // #ifdef APP-PLUS
        // APP平台：使用 Transcode 插件进行视频压缩
        if (this.compress) {
          try {
            // 使用 5+ API 进行视频转码压缩
            const targetPath = "_doc/compressed_" + Date.now() + ".mp4";

            // 视频转码参数
            const transcodeOptions = {
              audioBitrate: Math.floor(128 * this.videoQuality), // 音频码率
              videoBitrate: Math.floor(1000 * this.videoQuality), // 视频码率
              resolution: `${this.maxWidth}x${this.maxHeight}`, // 分辨率
              format: "mp4" // 输出格式
            };

            // 如果有视频转码插件，可以使用
            // 注意：这需要额外集成视频处理插件
            plus.video.transcode(
                filePath,
                targetPath,
                transcodeOptions,
                (outpath) => {
                  //console.log("视频压缩成功:", outpath);
                  resolve(outpath);
                },
                (error) => {
                  console.error("视频压缩失败:", error);
                  resolve(filePath); // 压缩失败时使用原视频
                }
            );
          } catch (err) {
            console.error('视频压缩处理失败:', err);
            resolve(filePath);
          }
        } else {
          resolve(filePath);
        }
        // #endif

        // #ifdef H5
        // H5平台：返回原路径，提示用户
        console.warn('H5平台暂不支持前端视频压缩，请在服务端处理');
        resolve(filePath)
        // #endif
      })
    },

    // 判断是否为视频文件
    isVideo(path) {
      if (!path) return false
      const videoExts = ['.mp4', '.mov', '.avi', '.wmv', '.flv', '.mkv', '.webm']
      const lowerPath = path.toLowerCase()
      return videoExts.some(ext => lowerPath.includes(ext))
    },

    // 判断是否为图片文件
    isImage(path) {
      if (!path) return false
      const imageExts = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp']
      const lowerPath = path.toLowerCase()
      return imageExts.some(ext => lowerPath.includes(ext))
    },

    // 获取文件类型
    getFileType(path) {
      if (this.isVideo(path)) {
        return 'video'
      } else if (this.isImage(path)) {
        return 'image'
      }
      return 'unknown'
    },

    // 播放视频
    playVideo(src) {
      this.currentVideoSrc = src
      this.showVideoModal = true
    },

    // 关闭视频弹窗
    closeVideoModal() {
      this.showVideoModal = false
      this.currentVideoSrc = ''
    },

    // 预览图片
    previewImage(src) {
      uni.previewImage({
        urls: [src]
      })
    },

    // 确保URL是完整的
    ensureFullUrl(url) {
      if (!url) return url;

      // 如果已经是完整URL，直接返回
      if (url.startsWith('http://') || url.startsWith('https://')) {
        return url;
      }

      // 如果是协议相对URL
      if (url.startsWith('//')) {
        return 'https:' + url;
      }

      // 如果是相对路径
      if (url.startsWith('/')) {
        return 'https://aiduk-1334050802.cos.ap-guangzhou.myqcloud.com' + url;
      }

      // 其他情况，默认加上https://
      return 'https://' + url;
    },

    // 视频错误处理
    onVideoError(event) {
      console.error('视频预览错误:', event);
    },

    // 模态框视频错误处理
    onModalVideoError(event) {
      console.error('模态框视频播放错误:', event);
      uni.showToast({
        title: '视频播放失败',
        icon: 'none'
      });
    },

    // 新增：执行上传并处理进度
    performUpload(file) {
      const startTime = Date.now()
      // 假设 uploadFileToTencentClound 返回一个 Promise，并支持进度回调
      uploadFileToTencentClound('aiduk', file.path, (progressEvent) => {
        if (progressEvent.lengthComputable) {
          const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
          this.$set(this.uploadProgressMap, file.path, percentCompleted)

          // 计算上传速率
          const currentTime = Date.now()
          const elapsedTime = (currentTime - this.uploadStartTimeMap[file.path]) / 1000 // 秒
          const uploadedBytes = progressEvent.loaded // 假设 progressEvent.loaded 是字节数
          const speed = elapsedTime > 0 ? (uploadedBytes / 1024 / elapsedTime).toFixed(2) : 0 // KB/s
          this.$set(this.uploadSpeedMap, file.path, speed)
        }
      }).then((evt) => {
        // 查找并更新对应的文件
        const index = this.mediaList.findIndex(item => item.path === file.path)
        if (index !== -1) {
          // 确保返回的路径有完整的URL前缀
          let fullPath = evt.path;
          if (fullPath && typeof fullPath === 'string') {
            // 如果没有协议前缀，添加https://
            if (!fullPath.startsWith('http://') && !fullPath.startsWith('https://')) {
              if (fullPath.startsWith('//')) {
                // 协议相对URL
                fullPath = 'https:' + fullPath;
              } else if (fullPath.startsWith('/')) {
                // 绝对路径
                fullPath = 'https://aiduk-1334050802.cos.ap-guangzhou.myqcloud.com' + fullPath;
              } else {
                // 可能是相对路径或其他格式
                fullPath = 'https://' + fullPath;
              }
            }
          }

          this.mediaList[index].path = fullPath;
          this.mediaList[index].status = 'done';
        }
        this.refreshValue()
      }).catch((error) => {
        // 处理上传错误
        console.error('上传失败:', error)
        const index = this.mediaList.findIndex(item => item.path === file.path)
        if (index !== -1) {
          this.mediaList[index].status = 'error'
        }
        uni.showToast({
          title: error.message || '上传失败',
          icon: 'none'
        })
      }).finally(() => {
        this.$delete(this.loadingMap, file.path)
        this.$delete(this.uploadProgressMap, file.path)
        this.$delete(this.uploadSpeedMap, file.path)
        this.$delete(this.uploadStartTimeMap,
